<template>
  <el-tree
    ref="dictTree"
    :data="trees"
    :default-expand-all="true"
    :highlight-current="true"
    :props="defProps"
    :expand-on-click-node="false"
    :style="$attrs.style"
    :show-checkbox="props.isMultiple"
    :current-node-key="chioseKey"
    :default-checked-keys="checkboxKey"
    :check-strictly="checkstrictly"
    node-key="DicValue"
    @node-click="chioseNode"
    @check-change="checkChange"
  >
    <template #default="{ node, data }">
      <div class="slot-t-node">
        <Icon
          v-if="data.style && data.style.icon"
          :icon="data.style.icon"
          :color="data.style.color"
          :style="{ marginRight: '5px' }"
        />
        <span>{{ node.label }}</span>
      </div>
    </template>
  </el-tree>
</template>

<script setup lang="ts">
import { getTrees } from '@/api/base/treeDicItem'
import { propTypes } from '@/utils/propTypes'
import { useAppStore } from '@/store/modules/app'
import { ref, watch } from 'vue'
import { treeItem } from '../types'

const checkstrictly = ref<Boolean>(false)
const appStore = useAppStore()
const trees = ref<treeItem[]>([])
const chioseKey = ref(null)
const dictTree = ref(null)
const checkboxKey = ref<string[]>([])
const valKey = {}
const cache = {}
const defProps = {
  key: 'DicValue',
  label: 'DicText',
  children: 'Children'
}
const emit = defineEmits(['load', 'change', 'update:modelValue'])
const props = defineProps({
  dicId: propTypes.string,
  parentId: propTypes.string,
  isMultiple: propTypes.bool.def(false),
  isAutoChiose: propTypes.bool.def(false),
  isChioseEnd: propTypes.bool.def(true),
  modelValue: propTypes.any
})
const load = async () => {
  const res = await getTrees(props.dicId, props.parentId)
  if (res == null) {
    return []
  }
  res.forEach((a) => {
    initTree(a)
  })
  return res
}
const initTree = (res) => {
  if (res.DicValue != null && res.DicValue !== '') {
    valKey[res.DicValue] = res.DicText
  }
  checkstrictly.value = props.isChioseEnd == false
  if (res.Children != null && res.Children.length > 0) {
    res.style = {
      icon: 'ep:folder-opened',
      color: '#409eff'
    }
    res.isEnd = false
    res.Children.forEach((c) => {
      initTree(c)
    })
  } else {
    res.style = {
      icon: 'ep:document',
      color: appStore.getIsDark ? '#fff' : '#000'
    }
    res.isEnd = true
  }
  cache[res.DicValue] = {
    value: res.DicValue,
    text: res.DicText,
    isEnd: res.isEnd
  }
}
const findDef = (list): string | null => {
  if (props.isChioseEnd === false) {
    return list[0].DicValue
  }
  for (let i = 0; i < list.length; i++) {
    const t = list[i]
    if (t.isEnd) {
      return t.DicValue
    } else if (t.Children != null && t.Children.length > 0) {
      const res = findDef(t.Children)
      if (res != null) {
        return res
      }
    }
  }
  return null
}
const loadTree = async () => {
  if (props.modelValue == null || props.modelValue.length === 0) {
    checkboxKey.value = []
  }
  const res = await load()
  trees.value = res
  const e = {
    isMultiple: props.isMultiple,
    text: valKey,
    cache: cache,
    value: []
  }
  checkboxKey.value = []
  if (props.isAutoChiose && res.length > 0) {
    const chioseVal = findDef(res)
    if (props.isMultiple) {
      checkboxKey.value.push(chioseVal)
      emit('update:modelValue', chioseKey.value)
    } else {
      chioseKey.value = chioseVal
      emit('update:modelValue', chioseVal)
    }
    e.value.push(chioseVal)
  } else {
    chioseKey.value = null
  }
  emit('load', e)
}
const autoChiose = (data) => {
  if (data.Children && data.Children.length !== 0) {
    let isSet = false
    data.Children.forEach((c) => {
      if (c.type === 'unit') {
        return
      }
      if (!checkboxKey.value.includes(c.DicValue)) {
        checkboxKey.value.push(c.DicValue)
        isSet = true
        autoChiose(c)
      }
    })
    return isSet
  }
  return false
}
const chioseNode = (node) => {
  const e = {
    isMultiple: props.isMultiple,
    cache: cache,
    text: valKey,
    value: null
  }
  if (node !== null) {
    chioseKey.value = node.DicValue
    e.value = [node.DicValue]
  } else {
    chioseKey.value = null
  }
  emit('update:modelValue', chioseKey.value)
  emit('change', e)
}
const checkChange = (data, checked, indeterminate) => {
  console.log(data)
  const index = checkboxKey.value.findIndex((c) => c === data.DicValue)
  if (checked) {
    if (index !== -1) {
      return
    }
    checkboxKey.value.push(data.DicValue)
    if (autoChiose(data)) {
      dictTree.value.setCheckedKeys(checkboxKey, false)
    }
  } else if (index === -1) {
    return
  } else {
    checkboxKey.value.splice(index, 1)
  }
  const e = {
    isMultiple: props.isMultiple,
    cache: cache,
    text: valKey,
    value: checkboxKey.value
  }
  emit('update:modelValue', e.value)
  emit('change', e)
}
watch(
  () => props.dicId,
  (dic: string) => {
    if (dic) {
      loadTree()
    }
  },
  {
    immediate: true
  }
)
watch(
  () => props.modelValue,
  (val) => {
    if (props.isMultiple) {
      if (val == null) {
        checkboxKey.value = []
      } else {
        checkboxKey.value = Array.isArray(val) ? val : [val]
      }
      chioseKey.value = null
    } else {
      chioseKey.value = val
    }
  },
  {
    immediate: true
  }
)
</script>
